package com.googlecode.websecuritychecks.filter;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import com.googlecode.websecuritychecks.model.*;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import com.googlecode.websecuritychecks.*;

public class WebSecurityChecksFilter implements Filter {

    private CheckFailureCallback checkFailureCallback;
    private List<Check> checks = new ArrayList<>();
    private Element checkXmlRootElement;

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(final ServletRequest arg0, final ServletResponse arg1, final FilterChain arg2) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) arg0;
        HttpServletResponse httpServletResponse = (HttpServletResponse) arg1;

        for (Check check : checks) {
            if (httpServletResponse.isCommitted() == false && checkXmlRootElement != null) {
                check.check(checkXmlRootElement, httpServletRequest, httpServletResponse);
            }
        }

        // Chain if the response is not committed yet.
        if (httpServletResponse.isCommitted() == false) {
            arg2.doFilter(arg0, arg1);
        }
    }

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        // Load the file and register a file listener.
        String checksFile = filterConfig.getInitParameter("checksFile");
        try {
            if (checksFile != null && checksFile.trim().length() > 0) {
                checkXmlRootElement = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(checksFile)).getDocumentElement();
            } else {
                checkXmlRootElement = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(WebSecurityChecksFilter.class.getClassLoader().getResourceAsStream("DefaultWebSecurityChecks.xml")).getDocumentElement();
            }
        } catch (SAXException | IOException | ParserConfigurationException e) {
            e.printStackTrace();
        }
        checks.add(new ParameterValueCheck());
        checks.add(new ParameterNameCheck());
        checks.add(new CSRFCheck());

        if (checkFailureCallback != null) {
            for (Check check : checks) {
                check.addCheckFailureCallback(checkFailureCallback);
            }
        }
    }

    /**
     * @param checkFailureCallback
     *            the checkFailureCallback to set
     */
    public void setCheckFailureCallback(final CheckFailureCallback checkFailureCallback) {
        this.checkFailureCallback = checkFailureCallback;
    }

}
